﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace LinqDemo
{
    public class Mapping<TIn, TOut>
    {
        private static Func<TIn, TOut> func = null;
        public static TOut To(TIn tIn)
        {
            if (func == null)
            {
                ParameterExpression inParam = Expression.Parameter(typeof(TIn), "t");
                List<MemberBinding> bindList = new List<MemberBinding>();
                foreach (var item in typeof(TOut).GetProperties())
                {
                    var property = typeof(TIn).GetProperty(item.Name);
                    if (property != null)
                    {
                        var p2 = Expression.Property(inParam, item.Name);
                        bindList.Add(Expression.Bind(item, p2));
                    }
                }

                MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), bindList);
                Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, inParam);
                func = lambda.Compile();
            }
            return func(tIn);
        }
    }
}
